package com.googlecode.mbhsrobopro.controller.components;
import java.awt.AWTException;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.JPanel;

import com.googlecode.mbhsrobopro.controller.events.ValueChangedEvent;
import com.googlecode.mbhsrobopro.controller.listeners.ValueChangedListener;

/**
 * 
 * @author Matt Bernstein
 *
 */

public class ArcadeDrive extends JPanel implements KeyListener, MouseMotionListener {
	
	private static final long serialVersionUID = 1L;
	private double speed;
	private double turningScale;
	private boolean space=false, shift=false, pd=false;
	private boolean l=false, r=false, f=false, b=false;
	//Space bar turns off turning
	//shift locks speed
	//period turns it all off
	int xOr;
	int yOr;
	
	private ArrayList<ValueChangedListener> listeners = new ArrayList<ValueChangedListener>();
	
	public ArcadeDrive(){
		setPreferredSize(new Dimension(600,600));
		addMouseMotionListener(this);
		addKeyListener(this);
		setVisible(true);
	}
	
	public void paint(Graphics g){
		Graphics2D g2 = (Graphics2D)g;
		xOr = getWidth()/2;
		yOr = getHeight()/2;
		g2.translate(xOr, yOr);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setStroke(new BasicStroke(3f));
		g2.setColor(new Color(198,207,53));
		g2.fillRect(-xOr, -yOr, getWidth(), getHeight());
		g2.setColor(Color.BLACK);
		g2.drawLine(0,-yOr, 0, yOr);
		g2.drawLine(-xOr, 0, xOr, 0);
		g2.setStroke(new BasicStroke(1f));
		g2.setFont(new Font("SansSerif", Font.PLAIN, 12));
		int count = -110;
		g2.setFont(new Font("SansSerif", Font.PLAIN, 11));
		for(int i = yOr; i >= -yOr; i -= getHeight()/20){
			g2.drawLine(-xOr, i, xOr, i);
			g2.drawString((count>=10? "+" + count + "%": count + "%" ), 8, (count>=10? i+14: i+27));
			if (count==-10){count=10;}else{count+=10;}
		}
		count = -8;
		for(int i = -xOr; i <= xOr; i+= getWidth()/12){
			g2.drawLine(i, -yOr, i, yOr);
			g2.drawString((count<=-3? "R " + -count + "/12": "L " +  count + "/12"), (count<=-3? i+2:i+16), 12);
			if(count==-3){count=3;}else{count+=1;}
		}
	}
	
	public void keyTyped(KeyEvent e) {}
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_ESCAPE)
			System.exit(0);
		if(e.getKeyCode()==KeyEvent.VK_SPACE)
			space = true;
		if(e.getKeyCode()==KeyEvent.VK_SHIFT)
			shift = true;
	}
	public void keyReleased(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_SPACE)
			space = false;
		if(e.getKeyCode()==KeyEvent.VK_SHIFT)
			shift = false;
		if (e.getKeyCode()==KeyEvent.VK_PERIOD)
			if(pd){shift=false;space=false;pd=false;}
			else{
				pd=true;
				speed=0;
				shift=true;
				space=true;
				Robot r;
				try {r = new Robot();
				
				r.mouseMove(this.getX()+xOr, this.getY()+yOr);
				}catch (AWTException e1) {}	
			}
	}
	public void mouseDragged(MouseEvent e) {}
	public void mouseMoved(MouseEvent e) {
		int x = e.getX()-xOr;
		double y = e.getY()-yOr;
		System.out.println(e.getPoint());
		if(!space) turningScale = (Math.abs(x/50.)+6)/12;
		else turningScale = 1;
		if(!shift) speed = (int)(Math.abs((-y/yOr)*512));
		if (x < 0){l=true;r=false;}
		else{r=true;l=false;}
		if(y < 0){f = true;b = false;}
		else{b=true;f=false;}
		fireValueChanged(new ValueChangedEvent(this, (int) speed, turningScale, f, b, l, r));
	}
	
	public int getMotorSpeed(){
		return (int) speed;
	}
	
	public double getTurningScale(){
		return turningScale;
	}
	
	public void zero(){
		Robot r = null;
		try {r = new Robot();} catch (AWTException e) {}
		r.keyPress(KeyEvent.VK_PERIOD);
		r.keyRelease(KeyEvent.VK_PERIOD);
		
	}
	
	public synchronized void addValueChangedListener(ValueChangedListener v) {
		listeners.add(v);
	}
	
	public synchronized void removeValueChangedListener(ValueChangedListener v) {
		listeners.remove(v);
	}
	
	public void fireValueChanged(ValueChangedEvent v) {
		for (ValueChangedListener l : listeners)
			l.valueChanged(v);
	}
	
	public boolean isForward(){
		return f;
	}
	
	public boolean isBackwards(){
		return b;
	}
	
	public boolean isRight(){
		return r;
	}
	
	public boolean isLeft(){
		return l;
	}
}
